"""
/***************************************************************************
GridCreator
A QGIS plugin
Creates a new polygon grid layer.
                                                         -------------------
begin                                : 2009-10-01 
copyright                        : (C) 2009 by Mark Baas
email                                : mark.baas123@gmail.com 
 ***************************************************************************/

/***************************************************************************
 *                                                                                                                                                 *
 *     This program is free software; you can redistribute it and/or modify    *
 *     it under the terms of the GNU General Public License as published by    *
 *     the Free Software Foundation; either version 2 of the License, or         *
 *     (at your option) any later version.                                                                     *
 *                                                                                                                                                 *
 ***************************************************************************/
"""
# Import the PyQt and QGIS libraries
from PyQt4.QtCore import * 
from PyQt4.QtGui import *
from qgis.core import *
# Initialize Qt resources from file resources.py
import resources
# Import the code for the dialog
from GridCreatorDialog import GridCreatorDialog

import os, os.path

class GridCreator: 

    def __init__(self, iface):
        # Save reference to the QGIS interface
        self.iface = iface

    def initGui(self):    
        # Create action that will start plugin configuration
        self.action = QAction(QIcon(":/plugins/gridcreator/icon.png"), \
                "Create Grid", self.iface.mainWindow())
        # connect the action to the run method
        QObject.connect(self.action, SIGNAL("triggered()"), self.run) 

        # Add toolbar button and menu item
        self.iface.addToolBarIcon(self.action)
        self.iface.addPluginToMenu("&Create Grid", self.action)

    def unload(self):
        # Remove the plugin menu item and icon
        self.iface.removePluginMenu("&Create Grid",self.action)
        self.iface.removeToolBarIcon(self.action)

    # run method that performs all the real work
    def run(self): 
        # create and show the dialog 
        dlg = GridCreatorDialog(self.dlg_ok) 
        # show the dialog
        dlg.exec_()
    
    def dlg_ok(self, dlg):
        #if result == 1:
            # get dlg info
            layer = dlg.getLayer()
            size = dlg.getSize()
            output = dlg.getOutput()
            progress = dlg.ui.progressBar
            
            self.createGrid(layer, size, output, progress)
            addToTOC = QMessageBox.question(dlg, "Grid Creator", "Created output shapefile:" + "\n" + unicode(output) + "\n\nWould you like to add the new layer to the TOC?", QMessageBox.Yes, QMessageBox.No, QMessageBox.NoButton)
            if addToTOC == QMessageBox.Yes:
                self.addShapeToCanvas(unicode(output))
                
    # Convinience function to add a vector layer to canvas based on input shapefile path ( as string )
    def addShapeToCanvas(self, shapeFilePath):
        shapeFilePathList = shapeFilePath.split( "/" )
        layerName = QString( shapeFilePathList[len(shapeFilePathList)-1] )
        if layerName.endsWith( ".shp" ):
	        layerName = unicode( layerName ).rstrip( ".shp" )
        vlayer_new = QgsVectorLayer( shapeFilePath, layerName, "ogr" )

        if vlayer_new.isValid():
	        QgsMapLayerRegistry.instance().addMapLayer(vlayer_new)
	        return True
        else:   
	        return False
	                
    def createGrid(self, layer, size, output, pb):
            # get provider            
            pr = layer.dataProvider()

            # get basic info from layer
            crs = pr.crs()
            geotype = pr.geometryType()
            enc = pr.encoding()

            # start data retreival: fetch geometry and all attributes for each feature
            pr.select(pr.attributeIndexes(), QgsRectangle(), True)

            # Featuer placeholder
            feat = QgsFeature()

            minlat = 1e1000
            minlon = 1e1000
            maxlat = -1e1000
            maxlon = -1e1000
            # Go through all the features to find min/max latitude and longitude
            while pr.nextFeature(feat):
                # fetch geometry
                geom = feat.geometry()
                # show some information about the feature
                if geom.type() == QGis.Polygon:
                    x = geom.asPolygon()
                    for ring in x:
                        lats = []
                        lons = []
                        if ring == []: continue
                        for lat, lon in ring:
                            lats.append(lat)
                            lons.append(lon)

                        minlat = min(min(lats),minlat)
                        minlon = min(min(lons),minlon)
                        maxlat = max(max(lats),maxlat)
                        maxlon = max(max(lons),maxlon)

                elif geom.type() == QGis.Point:
                    lat,lon = geom.asPoint()
                    minlat = min(lat,minlat)
                    minlon = min(lon,minlon)
                    maxlat = max(lat,maxlat)
                    maxlon = max(lon,maxlon)  
                elif geom.type() == QGis.Line:
                    x = geom.asPolyline()
                    lats = []
                    lons = []
                    if x == []: continue
                    for lat, lon in x:
                        lats.append(lat)
                        lons.append(lon)
                    minlat = min(min(lats),minlat)
                    minlon = min(min(lons),minlon)
                    maxlat = max(max(lats),maxlat)
                    maxlon = max(max(lons),maxlon)      
                    

                # fetch map of attributes
                attrs = feat.attributeMap()

                # attrs is a dictionary: key = field index, value = QgsFeatureAttribute
                # show all attributes and their values
                #   for (k,attr) in attrs.iteritems():
                #      print "%d: %s" % (k, attr.toString())

            #print "minlat = ",minlat
            #print "maxlat = ",maxlat
            #print "minlon = ",minlon
            #print "maxlon = ",maxlon
            
            # Create fields and filewriter
            fields = {}
            fields[0] = QgsField("id", QVariant.Int)
            #fields[1] = QgsField("name", QVariant.String)
            fn = output
            if os.path.exists(fn):
                for f in os.listdir(os.path.dirname(fn)):
                    f2 = os.path.dirname(fn)+os.sep+f
                    if f2.startswith(os.path.splitext(fn)[0]): os.remove(f2)
            if os.path.exists(fn): print "error, original file could not be removed", sys.exit()
            writer = QgsVectorFileWriter(output, pr.encoding(),fields, QGis.WKBPolygon , crs)


            # measure the distance to create amount of boxes
            d = QgsDistanceArea()
            d.setProjectionsEnabled(True)
            d.setSourceCrs(crs.srsid())

            dlon = d.measureLine(QgsPoint(minlat,minlon),QgsPoint(minlat,maxlon))
            dlat = d.measureLine(QgsPoint(minlat,minlon),QgsPoint(maxlat,minlon))
            
            d1 = int(dlon/size)
            d2 = int(dlat/size)

            #d = 50
            dlon = maxlon-minlon
            dlat = maxlat-minlat
            blon = dlon/d1
            blat = dlat/d2
            lat = minlat
            lon = minlon
            
            # progress
            pcnt = 0
            pb.setRange(0, d2*d1)
            
            for x in range(d2):
                lat1 = lat
                lat2 = lat+blat
                lon = minlon
                for y in range(d1):
                    lon1 = lon
                    lon2 = lon+blon

                    pol = [QgsPoint(lat1,lon1),QgsPoint(lat1,lon2),QgsPoint(lat2,lon2),QgsPoint(lat2,lon1)]
                    geom = QgsGeometry.fromPolygon([pol])

                    feature = QgsFeature()
                    feature.setGeometry(geom)
                    feature.addAttribute(0, QVariant(pcnt))
                    #feature.addAttribute(1, QVariant("Aap"))
                    writer.addFeature(feature)
                    
                    lon += blon
                    pcnt += 1
                    pb.setValue(pcnt)
                lat += blat            
